#include "srdatabase.h"

#include <QtCore>
#include <QDateTime>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>

#include <openssl/md5.h>

SRDatabase SRDatabase::dbInstance_;
QString SRDatabase::strFilename_ = "auditapi.db";

SRDatabase::SRDatabase(QObject *parent)
    : QObject(parent) {
}

SRDatabase::~SRDatabase() {
    if (sqlDatabase_.isOpen())
        sqlDatabase_.close();
}

QString SRDatabase::encryptionPswd(const QString &_pswd) {
    return _pswd;
    /// [1] MD5 第一次加密
    unsigned char ch_pswd[256] = {};
    char md5_pswd[256] = {};
    memcpy(ch_pswd,_pswd.toUtf8().data(),_pswd.toUtf8().length());
    MD5(ch_pswd, strlen((char*)ch_pswd),(unsigned char*)md5_pswd);

    /// [2] MD5("pswd"+MD5) 第二次加密
    std::string out_pswd("pswd:");
    out_pswd += md5_pswd;
    memset(md5_pswd,0,sizeof(md5_pswd));
    MD5((const unsigned char*)out_pswd.c_str(),out_pswd.length(),
        (unsigned char*)md5_pswd);

    /// [3] 整理返回值
    QString ret_pswd = QString::fromUtf8(md5_pswd);
#ifdef QT_DEBUG
    qDebug() << "pswd" << ret_pswd;
#endif
    return ret_pswd;
}

SRDatabase *SRDatabase::DB(void) {
    if (!SRDatabase::isExist()) {
#ifdef QT_DEBUG
        qFatal("error: please register db first.");
#endif
        return Q_NULLPTR;
    }

    return &dbInstance_;
}

int SRDatabase::open(const QString &_user,
                     const QString &_pswd,
                     QString &out_userName) {
    if (sqlDatabase_.isOpen()) {
        // 指定的服务已经存在。
//        qCritical("specified service already exists");
        sqlDatabase_.close();
//        return 1073;
    }
    int ret = -1;
    do {

        if (!sqlDatabase_.isOpen()) {
            if (QSqlDatabase::contains(strFilename_)) {
                sqlDatabase_ = QSqlDatabase::database(strFilename_);
            }
            else {
                sqlDatabase_ = QSqlDatabase::addDatabase("QSQLITE");
                sqlDatabase_.setDatabaseName(strFilename_);
        //        sqlDatabase_.setUserName(_user);
        //        sqlDatabase_.setPassword(_pswd);
            }
        }
        if (!sqlDatabase_.open()) {
            /// @remark : 弹出一个提示框
            qWarning() << "Failed to connect database."
                       << sqlDatabase_.lastError();
            // 系统无法打开指定的设备或文件。x
            ret = 110;
            break;
        }

        QSqlQuery query(sqlDatabase_);
        QString sql_query_user;
        QString md5_pswd = encryptionPswd(_pswd);

        sql_query_user = QString("select name from audit_account \
                                     where user = '%1' AND pswd = '%2';")
                            .arg(_user).arg(md5_pswd);
#ifdef QT_DEBUG
        qDebug() << sql_query_user;
#endif
//        qDebug() << query.exec(sql_query_user);
        if (!query.exec(sql_query_user)) {
            qCritical() << "login failed." << query.lastError();
            ret = -1;
            break;
        }
        while(query.next()) {
            out_userName = query.value(0).toString();
            ret = 0;
        }

        user_ = _user;
        pswd_ = _pswd;
        userName_ = out_userName;
//        qCritical() << out_userName << "login success.";

    } while(false);
    return ret;
}

int SRDatabase::close(void) {
    sqlDatabase_.close();
    return 0;
}

int SRDatabase::checkUser(const QString &_user, const QString &_pswd)
{
    if (!sqlDatabase_.isOpen()) {
        if (QSqlDatabase::contains(strFilename_)) {
            sqlDatabase_ = QSqlDatabase::database(strFilename_);
        }
        else {
            sqlDatabase_ = QSqlDatabase::addDatabase("QSQLITE");
            sqlDatabase_.setDatabaseName(strFilename_);
    //        sqlDatabase_.setUserName(_user);
    //        sqlDatabase_.setPassword(_pswd);
        }

        if (!sqlDatabase_.open()) {
            /// @remark : 弹出一个提示框
            qWarning() << "Failed to connect database."
                       << sqlDatabase_.lastError();
            // 系统无法打开指定的设备或文件。x
            return 110;

        }
    }
    int ret = -1;
    do {

        QSqlQuery query(sqlDatabase_);
        QString sql_query_user;
        QString md5_pswd = encryptionPswd(_pswd);

        sql_query_user = QString("select name from audit_account \
                                     where user = '%1' AND pswd = '%2';")
                            .arg(_user).arg(md5_pswd);
#ifdef QT_DEBUG
        qDebug() << sql_query_user;
#endif
//        qDebug() << query.exec(sql_query_user);
        if (!query.exec(sql_query_user)) {
            qCritical() << "check failed." << query.lastError();
            ret = -1;
            break;
        }
        while(query.next()) {
            ret = 0;
        }

    } while(false);
    return ret;
}

int SRDatabase::registerUser(const QString &_name, const QString &_user, const QString &_pswd)
{
    /// [1] 修改当前文件夹下的DB文件
    QString filename;
    DBPath(filename);

    if (!isExist()) {
        qWarning() << "register user db file not find!";
    }

#ifdef QT_DEBUG
    qDebug() << "filename :" << filename;
#endif

    /// [2] 检查当前注册的链接
    if (!sqlDatabase_.isOpen()) {
        if (QSqlDatabase::contains(strFilename_)) {
            qDebug() << "if (QSqlDatabase::contains(strFilename_)) {";
            sqlDatabase_ = QSqlDatabase::database(strFilename_);
        }
        else {
            sqlDatabase_ = QSqlDatabase::addDatabase("QSQLITE");
            sqlDatabase_.setDatabaseName(strFilename_);
    //        sqlDatabase_.setUserName(_user);
    //        sqlDatabase_.setPassword(_pswd);
        }
    }
    if (!sqlDatabase_.open()) {
        /// @remark : 弹出一个提示框
        qWarning() << "Error: Failed to connect database." << sqlDatabase_.lastError();
        return 4;
    }

    /// [4] 插入注册信息
    QSqlQuery query(sqlDatabase_);
    QString md_pswd = encryptionPswd(_pswd);

    if (!query.exec(QString("INSERT INTO audit_account (name,user,pswd)\
                                VALUES ('%1', '%2', '%3');")
                     .arg(_name).arg(_user).arg(md_pswd))) {
        qInfo("register db failed.");
        qWarning() << query.lastError();
        return -1;
    }

    qDebug("register user success.");
    return 0;
}

int SRDatabase::modifyPswd(const QString &_newPswd)
{
    int ret = -1;
    if (!sqlDatabase_.isOpen()) {
        if (QSqlDatabase::contains(strFilename_)) {
            sqlDatabase_ = QSqlDatabase::database(strFilename_);
        }
        else {
            sqlDatabase_ = QSqlDatabase::addDatabase("QSQLITE");
            sqlDatabase_.setDatabaseName(strFilename_);
        }
        if (!sqlDatabase_.open()) {
            /// @remark : 弹出一个提示框
            qWarning() << "Error: Failed to connect database." << sqlDatabase_.lastError();
            return 4;
        }
    }

    do {

        QSqlQuery query(sqlDatabase_);
        QString sql_query_user;
        QString md5_pswd = encryptionPswd(_newPswd);
        sql_query_user = QString("UPDATE audit_account " \
                                 " SET pswd = '%1' "\
                                 " WHERE user = '%2' ")
                            .arg(md5_pswd).arg(user_);
        qDebug() << "pswd modify: " << sql_query_user;
#ifdef QT_DEBUG
        qDebug() << sql_query_user;
#endif
//        qDebug() << query.exec(sql_query_user);
        if (!query.exec(sql_query_user)) {
            qCritical() << "modify failed." << query.lastError();
            ret = -1;
            break;
        }
        // 这里可以再 select 复查一次
        ret = 0;

    } while(false);
    return ret;

}

int SRDatabase::modifyUserName(const QString &_newName)
{
    Q_UNUSED(_newName);
    return 0;
}

int SRDatabase::execSql(const QString &_sql)
{
    int ret = -1;
    if (!sqlDatabase_.isOpen()) {
        if (QSqlDatabase::contains(strFilename_)) {
            sqlDatabase_ = QSqlDatabase::database(strFilename_);
        }
        else {
            sqlDatabase_ = QSqlDatabase::addDatabase("QSQLITE");
            sqlDatabase_.setDatabaseName(strFilename_);
        }
        if (!sqlDatabase_.open()) {
            /// @remark : 弹出一个提示框
            qWarning() << "Error: Failed to connect database." << sqlDatabase_.lastError();
            return 4;
        }
    }

    do {
        QSqlQuery query(sqlDatabase_);

        if (!query.exec(_sql)) {
            qCritical() << "exec sql failed." << query.lastError();
            ret = -1;
            break;
        }

        if (query.isSelect()) {
            qDebug() << "query.size" << query.size();
            if (query.size() > 0) {
                ret = 0;
                break;
            }
        }

        ret = 0;

    } while(false);
    return ret;
}

bool SRDatabase::isExist(void) {
    QFile file(QString("%1/%2").arg(QDir::currentPath())
               .arg(strFilename_));
    if(file.exists()) {
        return true;
    }
    return false;
}
int SRDatabase::registerDB(const QString &_name,
                           const QString &_user,
                           const QString &_pswd) {
    /// [1] 修改当前文件夹下的DB文件
    QString filename;
    DBPath(filename);

#ifdef QT_DEBUG
    qDebug() << "filename :" << filename;
#endif
    if (isExist()) {
        QFile::rename(filename, filename
               + QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz"));
    }

    /// [2] 检查当前注册的链接
    QSqlDatabase sql_database;
    if (!sql_database.isOpen()) {
        if (QSqlDatabase::contains(strFilename_)) {
            sql_database = QSqlDatabase::database(strFilename_);
        }
        else {
            sql_database = QSqlDatabase::addDatabase("QSQLITE");
            sql_database.setDatabaseName(strFilename_);
    //        sqlDatabase_.setUserName(_user);
    //        sqlDatabase_.setPassword(_pswd);
        }
    }
    if (!sql_database.open()) {
        /// @remark : 弹出一个提示框
        qWarning() << "Error: Failed to connect database." << sql_database.lastError();
        return 4;
    }

    /// [3] 开始注册数据库结构
    do {
        // 获得初始化的Sql语句
        QFile file(":/sql/auditapi");
        QSqlQuery query(sql_database);
        if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            qFatal("Can't open the file!");
            return 4;
        }
        while(!file.atEnd()) {
            QByteArray line = file.readLine();
            if (!query.exec(line)) {
                qWarning() << query.lastError();
                continue;
            }
        }
        file.close();

    } while(false);

    /// [4] 插入注册信息
    QSqlQuery query(sql_database);
    QString md_pswd = encryptionPswd(_pswd);

    if (!query.exec(QString("INSERT INTO audit_account (name,user,pswd)\
                                VALUES ('%1', '%2', '%3');")
                     .arg(_name).arg(_user).arg(md_pswd))) {
        qInfo("register db failed.");
        qWarning() << query.lastError();
        return -1;
    }


    /// [5] 清理资源
    sql_database.close();
    qDebug("register db success.");
    return 0;
}

void SRDatabase::DBPath(QString &path)
{
    path = QDir::currentPath();
    path += "/";
    path += strFilename_;
}
